package com.easylinkin.linkappapi.lobar.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.service.OSSService;
import com.easylinkin.linkappapi.common.utils.excel.ExcelReadUtil;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.mapper.DeviceMapper;
import com.easylinkin.linkappapi.deviceservice.service.DeviceServiceService;
import com.easylinkin.linkappapi.lobar.dto.UserProjectDTO;
import com.easylinkin.linkappapi.lobar.dto.app.LobarUserDTO;
import com.easylinkin.linkappapi.lobar.dto.excel.ExcelResultDTO;
import com.easylinkin.linkappapi.lobar.dto.excel.ExcelResultDetailDTO;
import com.easylinkin.linkappapi.lobar.entity.*;
import com.easylinkin.linkappapi.lobar.entity.emp.EmpUserBase;
import com.easylinkin.linkappapi.lobar.entity.emp.EmpUserBaseDTO;
import com.easylinkin.linkappapi.lobar.entity.vo.UserProjectSelectVO;
import com.easylinkin.linkappapi.lobar.mapper.*;
import com.easylinkin.linkappapi.lobar.service.UserProjectService;
import com.easylinkin.linkappapi.lobar.util.IdentityUtils;
import com.easylinkin.linkappapi.lobar.util.LobarUtils;
import com.easylinkin.linkappapi.lobar.util.PercentageUtils;
import com.easylinkin.linkappapi.lobar.util.UnzipFileVo;
import com.easylinkin.linkappapi.lobar.vo.AddressBookVo;
import com.easylinkin.linkappapi.lobar.vo.UserProjectVo;
import com.easylinkin.linkappapi.openapi.dto.ApiDownResultDTO;
import com.easylinkin.linkappapi.openapi.dto.systemDock.RealNameSystemDTO;
import com.easylinkin.linkappapi.openapi.mapper.SystemDockInfoMapper;
import com.easylinkin.linkappapi.openapi.mapper.SystemDockingMapper;
import com.easylinkin.linkappapi.openapi.service.OpenApiService;
import com.easylinkin.linkappapi.openapi.util.Base64Util;
import com.easylinkin.linkappapi.openapi.util.DataSyncUtil;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.rtfparserkit.rtf.Command.manager;

/**
 * <p>
 * 闸机表 服务实现类
 * </p>
 *
 * @author kanyuanfeng
 * @since 2022-04-13
 */
@Service
public class UserProjectServiceImpl extends ServiceImpl<UserProjectMapper, UserProject> implements
        UserProjectService {

    private static final Logger logger = LoggerFactory.getLogger(UserProjectServiceImpl.class);

    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;

    @Autowired
    private EmpUserBaseMapper empUserBaseMapper;

    @Autowired
    private UserCertificateMapper userCertificateMapper;

    @Autowired
    private GroupMapper groupMapper;

    @Autowired
    private OSSService ossService;

    @Autowired
    private GateMapper gateMapper;

    @Autowired
    private DeviceServiceService deviceServiceService;

    @Autowired
    private LinkappTenantMapper linkappTenantMapper;

    @Autowired
    private OpenApiService openApiService;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private LaborCompanyProjectMapper laborCompanyProjectMapper;

    @Autowired
    private UserProjectMapper userProjectMapper;

    @Autowired
    private UserRecordMapper userRecordMapper;

    @Autowired
    private UserStatisticsMapper userStatisticsMapper;

    @Autowired
    private UserGateLinkMapper userGateLinkMapper;

    @Autowired
    private UserBlacklistMapper userBlacklistMapper;

    @Resource
    private SystemDockingMapper dockingMapper;
    @Resource
    private SystemDockInfoMapper infoMapper;

    @Value("${photo.cache.directory}")
    private String photoDir;

    private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(UserProjectServiceImpl.class);

    /**
     * 增加
     *
     * @param userProject
     */
    @Override
    public void insert(UserProject userProject) {
        /**
         * 验证重复
         */
//        this.checkExist(userProject);
        //校验黑名单中是否存在
        this.checkBlackList(userProject);
        //设置基本属性
        //删除之前添加过的
        Set<String> ids = userProject.getIds();
        QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("user_id_", ids)
                .eq("tenant_id_", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        baseMapper.delete(queryWrapper);

        ids.forEach(id -> {
            EmpUserBase empUserBase = empUserBaseMapper.selectById(id);
            //冗余属性处理
            UserProject newUserProject = new UserProject();
            newUserProject.setUserId(id);
            newUserProject.setWorkType(empUserBase.getWorkType());
            newUserProject.setUserName(empUserBase.getName());
            newUserProject.setPhoto(empUserBase.getPhoto());
            newUserProject.setBirthday(empUserBase.getBirthday());
            newUserProject.setGender(empUserBase.getGender());
            newUserProject.setStatus(1);
            newUserProject.setGroupId(userProject.getGroupId());
            newUserProject.setEduFlie(userProject.getEduFlie());
            newUserProject.setEduState(userProject.getEduState());
            //添加当天当成入场时间
            if (null == newUserProject.getJoinTime()) {
                newUserProject.setJoinTime(new Date());
            }
            this.setBase(newUserProject);
            //处理班组长
//      setLead(userProject);
            //下发到闸机
            new Thread(() -> {
                empUserBase.setGroupId(userProject.getGroupId());
                Map<String, Object> map = this.userToGate(empUserBase, 1);
                if ((Boolean) map.get("flag")) {
                    UpdateWrapper<UserProject> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.set("gate_status_", 1)
                            .eq("tenant_id_", newUserProject.getTenantId())
                            .eq("user_id_", empUserBase.getId());
                    baseMapper.update(null, updateWrapper);
                }
            }).start();
            this.save(newUserProject);
        });
    }

    private void checkBlackList(UserProject userProject) {
        QueryWrapper<UserBlacklist> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id_", userProject.getUserId());
        queryWrapper.in("approval_status_", 0,1);
        List<UserBlacklist> userBlacklists = userBlacklistMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(userBlacklists)) {
            throw new BusinessException("该用户已存在黑名单中，无法添加");
        }
    }

    /**
     * 设置班组长
     *
     * @param userProject
     */
    private void setLead(UserProject userProject) {
        if (Integer.valueOf(1).equals(userProject.getIsGroupLeader())) {
            UpdateWrapper<UserProject> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("group_id_", userProject.getGroupId())
                    .set("is_group_leader_", 0);
            baseMapper.update(null, updateWrapper);
            Group group = groupMapper.selectById(userProject.getGroupId());
            group.setLeadUserId(userProject.getUserId());
            groupMapper.updateById(group);
        } else {
            UpdateWrapper<Group> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("lead_user_id_", null)
                    .eq("id", userProject.getGroupId());
            groupMapper.update(null, updateWrapper);
        }
    }

    /**
     * 根据id编辑
     *
     * @param userProject
     */
    @Override
    public void updateOne(UserProject userProject) {
        /**
         * 验证是否重复在职.验证班组是否退场
         */
        this.checkExist(userProject);
        this.setBase(userProject);
        this.updateById(userProject);
        //判断是否退场
        if (Integer.valueOf(0).equals(userProject.getStatus())) {
            Set<String> ids = new HashSet<>();
            ids.add(userProject.getId());
            delGateBatch(ids);
        }
        this.setSyncBase(userProject);
    }

    private void setSyncBase(UserProject userProject) {

        if (userProject.getId() != null) {
            UserProject up = userProjectMapper.selectById(userProject.getId());

            if (up != null) {
                EmpUserBase empUser = empUserBaseMapper.selectById(up.getUserId());
                if (empUser != null) {
                    EmpUserBaseDTO dto = new EmpUserBaseDTO();
                    UserProjectDTO userProjectDTO = new UserProjectDTO();
                    BeanUtils.copyProperties(up, userProjectDTO);
                    dto.setCompanyId(empUser.getCompanyId());
                    dto.setCompanyName(empUser.getCompanyName());
                    dto.setName(empUser.getName());
                    dto.setTelephone(empUser.getTelephone());
                    dto.setCard(empUser.getCard());
                    dto.setGroupName(empUser.getGroupName());
                    dto.setWorkType(up.getWorkType());
                    dto.setPhoto(empUser.getPhoto());
                    //dto.setId(empUser.getId());
                    userProjectDTO.setGroupId(up.getGroupId());
                    userProjectDTO.setGroupName(empUser.getGroupName());
                    dto.setUserProject(userProjectDTO);
                    syncToSystem(dto, 0);
                }
            }

        }
    }

    /**
     * @return
     * @Description: 根据条件，获取统计
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public Map<String, Long> getCount(UserProjectDTO userProjectDTO) {
        Map<String, Long> map = new HashMap<>();
        Page<UserProjectDTO> page = new Page<>();
        page.setSize(1);
        page.setCurrent(1);
        //项目id 过滤
        userProjectDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        //全部
        userProjectDTO.setStatus(2);
        IPage<UserProjectDTO> oneIPage = baseMapper.queryListByPage(page, userProjectDTO);
        map.put("one", oneIPage.getTotal());
        //在职
        userProjectDTO.setStatus(1);
        IPage<UserProjectDTO> twoIPage = baseMapper.queryListByPage(page, userProjectDTO);
        map.put("two", twoIPage.getTotal());
        //离职
        userProjectDTO.setStatus(0);
        IPage<UserProjectDTO> threeIPage = baseMapper.queryListByPage(page, userProjectDTO);
        map.put("three", threeIPage.getTotal());
        return map;
    }

    /**
     * @Description: 根据条件，获取可以添加到项目的用户
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public IPage<EmpUserBase> getBaseUsers(RequestModel<UserProjectDTO> requestModel) {
        Page page = requestModel.getPage();
        UserProject userProject = requestModel.getCustomQueryParams();
        //项目id 过滤
        userProject.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        IPage<EmpUserBase> empUserBaseIPage = empUserBaseMapper.getBaseUsers(page, userProject);
        //计算年龄
        empUserBaseIPage.getRecords().forEach(g -> {
            Date birthday = g.getBirthday();
            if (birthday != null) {
                int age = DateUtil.age(birthday, new Date());
                g.setAge(age);
            }
        });
        return empUserBaseIPage;
    }

    @Override
    public void insertEmp(EmpUserBaseDTO empUserBaseDTO) {
        EmpUserBase empUserBase = saveEmpBaseUser(empUserBaseDTO);
        empUserBaseDTO.getUserProject().setUserId(empUserBase.getId());
        //添加当天当成入场时间
        if (null == empUserBaseDTO.getUserProject().getJoinTime()) {
            empUserBaseDTO.getUserProject().setJoinTime(new Date());
        }
        empUserBaseDTO.getUserProject().setGateStatus(0);
        //设置班组长
        this.setLead(empUserBaseDTO.getUserProject());
        //下发到闸机
        new Thread(() -> {
            empUserBase.setGroupId(empUserBaseDTO.getUserProject().getGroupId());
            Map<String, Object> map = this.userToGate(empUserBase, 1);
            if ((Boolean) map.get("flag")) {
                UpdateWrapper<UserProject> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("gate_status_", 1)
                        .eq("tenant_id_", empUserBaseDTO.getUserProject().getTenantId())
                        .eq("user_id_", empUserBase.getId());
                baseMapper.update(null, updateWrapper);
            }
        }).start();
        //删除之前存在的删除数据
        QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id_", empUserBaseDTO.getUserProject().getUserId())
                .eq("tenant_id_", empUserBaseDTO.getUserProject().getTenantId());
        baseMapper.delete(queryWrapper);
        baseMapper.insert(empUserBaseDTO.getUserProject());
        //添加资质证书
        if (null != empUserBaseDTO.getUserCertificates()) {
            empUserBaseDTO.getUserCertificates().forEach(u -> {
                u.setUserId(empUserBase.getId());
                u.setCreatorId(empUserBaseDTO.getCreatorId());
                u.setModifyId(empUserBaseDTO.getModifyId());
                u.setCreateTime(empUserBaseDTO.getCreateTime());
                u.setModifyTime(empUserBaseDTO.getModifyTime());
                userCertificateMapper.insert(u);
            });
        }

        //同步到东西湖系统
        syncToSystem(empUserBaseDTO, 0);
    }

    @Override
    public EmpUserBase saveEmpBaseUser(EmpUserBaseDTO empUserBaseDTO) {
        //验证是否已存在bese库
        this.checkExistEmp(empUserBaseDTO);
        //判断是否已存在改项目中
        if (StringUtils.isNotBlank(empUserBaseDTO.getId())) {
            UserProjectDTO userId = baseMapper.findByUserId(empUserBaseDTO.getId(),
                    linkappUserContextProducer.getNotNullCurrent().getTenantId());
            if (null != userId) {
                throw new BusinessException("项目中已存在该人员");
            }
        }
        //设置基本属性
        this.setBaseEmp(empUserBaseDTO);
        //分开保存
        EmpUserBase empUserBase = new EmpUserBase();
        BeanUtils.copyProperties(empUserBaseDTO, empUserBase);
        if (StringUtils.isNotBlank(empUserBase.getId())) {
            empUserBaseMapper.updateById(empUserBase);
        } else {
            empUserBaseMapper.insert(empUserBase);
        }
        //同步到emp
        new Thread(() -> syncUser(empUserBase, StringUtils.isBlank(empUserBaseDTO.getUserProject().getTenantId())?"1":empUserBaseDTO.getUserProject().getTenantId())).start();
        return empUserBase;
    }

    /**
     * 同步到emp
     *
     * @param empUserBase
     */
    private void syncUser(EmpUserBase empUserBase, String tenantId) {
        new Thread(() -> {
            EmpUserBase param = new EmpUserBase();
            BeanUtils.copyProperties(empUserBase, param);
            if (null != param.getEmpUid()) {
                param.setId(param.getEmpUid() + "");
            } else {
                param.setId(null);
            }
            //查找projectId
            LinkappTenant linkappTenant = new LinkappTenant();
            if (StringUtils.isBlank(tenantId)) {
                linkappTenant.setId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
            } else {
                linkappTenant.setId(tenantId);
            }
            if (tenantId.equals("1")){
                param.setProjectId("1");
            }else {
                LinkappTenant tenant = linkappTenantMapper.selectLinkappTenant(linkappTenant);
                Optional.ofNullable(tenant).ifPresent(t -> param.setProjectId(t.getProjectId()));
            }
            ApiDownResultDTO resultDTO = openApiService.syncUser(param);
            if (null != resultDTO && null == empUserBase.getEmpUid()) {
                //保存linkthing对应数据id
                Object dtoData = resultDTO.getData();
                if (null != dtoData) {
                    empUserBase.setEmpUid(new Long((Integer) dtoData));
                    empUserBaseMapper.updateById(empUserBase);
                }
            }
        }).start();
    }

    /**
     * @Description: 编辑用户(emp)
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public void updateByIdEmp(EmpUserBaseDTO empUserBaseDTO) {
        /**
         * 验证重复
         */
        this.checkExistEmp(empUserBaseDTO);
        //设置基本属性
        this.setBaseEmp(empUserBaseDTO);
        //分开保存
        EmpUserBase empUserBase = new EmpUserBase();
        BeanUtils.copyProperties(empUserBaseDTO, empUserBase);
        empUserBaseMapper.updateById(empUserBase);
        //同步到emp
        syncUser(empUserBase, empUserBaseDTO.getUserProject().getTenantId());
        //设置班组长
        this.setLead(empUserBaseDTO.getUserProject());
        baseMapper.updateById(empUserBaseDTO.getUserProject());

        //资质证书保存
        //删除
        QueryWrapper<UserCertificate> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id_", empUserBaseDTO.getId());
        userCertificateMapper.delete(queryWrapper);
        //新增
        if (null != empUserBaseDTO.getUserCertificates()) {
            empUserBaseDTO.getUserCertificates().forEach(u -> {
                u.setUserId(empUserBaseDTO.getId());
                u.setCreatorId(empUserBaseDTO.getCreatorId());
                u.setModifyId(empUserBaseDTO.getModifyId());
                u.setCreateTime(empUserBaseDTO.getCreateTime());
                u.setModifyTime(empUserBaseDTO.getModifyTime());
                userCertificateMapper.insert(u);
            });
        }

        syncToSystem(empUserBaseDTO, 0);
    }

    /**
     * @Description: 根据id查询用户详情(基础属性)
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public EmpUserBaseDTO getByIdEmp(String id) {
        EmpUserBaseDTO empUserBaseDTO = new EmpUserBaseDTO();
        UserProjectDTO userProjectDTO = baseMapper.findById(id);
        String userId = userProjectDTO.getUserId();
        EmpUserBase empUserBase = empUserBaseMapper.selectById(userId);
        //计算年龄
        userProjectDTO.setAge(DateUtil.age(empUserBase.getBirthday(), new Date()));
        //计算在岗和出勤天数
        long sum = DateUtil.between(DateUtil.beginOfDay(userProjectDTO.getJoinTime()), new Date(), DateUnit.DAY);
        userProjectDTO.setSum((int) sum + 1);
        QueryWrapper<UserRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id_", userProjectDTO.getTenantId())
                .ge("record_time_", DateUtil.beginOfDay(userProjectDTO.getJoinTime()))
                .eq("user_id_", userProjectDTO.getUserId())
                .ne("record_type_", 0);
        Integer integer = userRecordMapper.selectCount(queryWrapper);
        userProjectDTO.setOn(integer);
        BeanUtils.copyProperties(empUserBase, empUserBaseDTO);
        empUserBaseDTO.setUserProject(userProjectDTO);
        empUserBaseDTO.setGroupId(userProjectDTO.getGroupId());
        return empUserBaseDTO;
    }

    @Override
    public EmpUserBaseDTO getByUserIdAndTenantIEmp(String userId, String tenantId) {
        UserProjectDTO userProjectDTO = baseMapper.findByUserId(userId, tenantId);
        EmpUserBase empUserBase = empUserBaseMapper.selectById(userId);
        if (null != empUserBase) {
            EmpUserBaseDTO empUserBaseDTO = new EmpUserBaseDTO();
            //计算年龄
            userProjectDTO.setAge(DateUtil.age(empUserBase.getBirthday(), new Date()));
            //计算在岗和出勤天数
            long sum = DateUtil.between(userProjectDTO.getJoinTime(), new Date(), DateUnit.DAY);
            userProjectDTO.setSum((int) sum + 1);
            QueryWrapper<UserRecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tenant_id_", userProjectDTO.getTenantId())
                    .le("record_time_", userProjectDTO.getJoinTime())
                    .eq("user_id_", userProjectDTO.getUserId())
                    .ne("record_type_", 0);
            Integer integer = userRecordMapper.selectCount(queryWrapper);
            userProjectDTO.setOn(integer);
            BeanUtils.copyProperties(empUserBase, empUserBaseDTO);
            empUserBaseDTO.setUserProject(userProjectDTO);
            return empUserBaseDTO;
        }
        return null;
    }

    /**
     * @Description: 根据班组id查询，不分页
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public List<EmpUserBase> queryByGroupId(UserProjectDTO userProjectDTO) {
        List<EmpUserBase> empUserBases = empUserBaseMapper.queryByGroupId(userProjectDTO);
        empUserBases.removeIf(e -> null == e);
        return empUserBases;
    }

    @Override
    public void delBatch(Set<String> ids) {
        ids.forEach(id -> {
            //删除资质证书
            UserProject userProject = baseMapper.selectById(id);
            QueryWrapper<UserCertificate> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id_", userProject.getUserId());
            userCertificateMapper.delete(queryWrapper);
        });
        UpdateWrapper<UserProject> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("delete_state_", 0).set("status_", 0)
                .in("id", ids);
        baseMapper.update(null, updateWrapper);
        //从闸机里面删除
        delGateBatch(ids);
    }

    /**
     * 从闸机里面移除
     *
     * @param ids
     */
    @Override
    public void delGateBatch(Set<String> ids) {
        new Thread(() ->
                ids.forEach(id -> {
                    //从闸机删除
                    delGateByUserId(id);
                })
        ).start();
    }

    /**
     * 从闸机删除
     *
     * @param id
     */
    private void delGateByUserId(String id) {
        //查询用户
        UserProject userProject = baseMapper.selectById(id);
        if (null != userProject) {
            EmpUserBase empUserBase = empUserBaseMapper.selectById(userProject.getUserId());
            empUserBase.setGroupId(userProject.getGroupId());
            QueryWrapper<Gate> queryWrapper = new QueryWrapper<>();
            //查询已绑定编号的闸机
            String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
            queryWrapper.eq("tenant_id_", tenantId)
                    .isNotNull("code_").like("access_", 1);
            List<Gate> gates = gateMapper.selectList(queryWrapper);
            Set<String> codeSet = gates.stream().map(g -> g.getCode()).collect(Collectors.toSet());
            if (null != codeSet && codeSet.size() > 0) {
                //查询在不在设备库里
                QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
                deviceQueryWrapper.in("code", codeSet);
                List<Device> devices = deviceMapper.selectList(deviceQueryWrapper);
                Set<String> codes = devices.stream().map(g -> g.getCode()).collect(Collectors.toSet());
                codes.forEach(code -> {
                    //非实名制的才要删除
                    if (Integer.valueOf(0).equals(userProject.getRealSys())) {
                        delGate(empUserBase, code, false);
                    }
                });
            }
        }
    }

    @Override
    public RestMessage appAddressBook(UserProjectVo userProjectVo) {
        //获取当前用户信息
        LinkappUser curAppUser = linkappUserContextProducer.getCurrent();
        Assert.notNull(curAppUser, "用户登录失效");
        String tenantId = curAppUser.getTenantId();
        //参数校验
        Assert.isTrue(StringUtils.isNotBlank(tenantId), "项目ID为空");

        userProjectVo.getUserProject().setTenantId(tenantId);

        //出参数据
        List<AddressBookVo> ls = new ArrayList<>();
        //查询数据（这里是一次性获取数据，没有进行层级异步获取数据，好处是前端关键字过滤方便，缺点就是后端压力大）
        List<UserProjectDTO> userLs = this.baseMapper.queryUserProjectDtoList(userProjectVo);
        if (CollectionUtil.isNotEmpty(userLs)) {
            //组织数据方案1，组织树形数据，利用hutool的TreeUtil（考虑到层级不深，似乎大材小用）

            //组织数据方案2，使用stream的进行操作（这种对于多层级的数据就有点繁琐了）
            //数据转map，提炼公司信息
            Map<String, String> companyMap = userLs.stream().collect(
                    Collectors.toMap(UserProjectDTO::getCompanyId, UserProjectDTO::getCompanyName,
                            (o, n) -> n));

            //按照公司分组
            Map<String, List<UserProjectDTO>> userMap = userLs.stream()
                    .collect(Collectors.groupingBy(UserProjectDTO::getCompanyId));

            //将2组数据一起做数据处理转出参
            userMap.entrySet().stream().forEach(c -> {
                String tmpCompanyId = c.getKey();
                List<UserProjectDTO> tmpUserLs = c.getValue();
                AddressBookVo addressBookVo = new AddressBookVo();
                addressBookVo.setId(tmpCompanyId);
                String companyName = companyMap.get(tmpCompanyId);
                addressBookVo.setName(companyName);
                addressBookVo.setNum(CollectionUtil.size(tmpUserLs));
                addressBookVo.setUserList(tmpUserLs);
                ls.add(addressBookVo);
            });
        }

        return RestBuilders.successBuilder().data(ls).build();
    }

    /**
     * @Description: 下发到闸机
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public Map<String, Object> upToGate(String id) {
        Map<String, Object> map = new HashMap<>();
        //查询用户
        UserProject userProject = baseMapper.selectById(id);
        if (null != userProject) {
            EmpUserBase empUserBase = empUserBaseMapper.selectById(userProject.getUserId());
            empUserBase.setGroupId(userProject.getGroupId());
            map = this.userToGate(empUserBase, 1);
            if ((Boolean) map.get("flag")) {
                userProject.setGateStatus(1);
                baseMapper.updateById(userProject);
            }
        }
        return map;
    }

    /**
     * 批量导入花名册
     * isReal true 实名制 反之非实名制
     */
    @Override
    public ExcelResultDTO importExcel(MultipartFile file, Integer type, String tenantId, Boolean isReal)
            throws Exception {
        List<List<String>> excelList;
        if (isReal) {
            excelList = ExcelReadUtil.getExcelInfo(file, 1, -1, -1);
        } else {
            excelList = ExcelReadUtil.getExcelInfo(file, 2, -1, -1);
        }

        if (excelList.size() > 0 && excelList.get(0).size() < (isReal ? 16 : 8)) {
            throw new BusinessException("模板错误,请选择正确的文件导入");
        }
        //创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(20);
        //创建一个Set保存excel本身的身份证号码
        CompletableFuture<ExcelResultDTO> completableFuture = CompletableFuture
                .supplyAsync(() -> {
                    ExcelResultDTO excelResultDTO = getExcelResultDTO(type, excelList, tenantId, isReal);
                    return excelResultDTO;
                }, executorService);
        ExcelResultDTO excelResultDTO = completableFuture.get();
        return excelResultDTO;
    }

    /**
     * 执行导入和验证
     * isReal true 实名制 反之非实名制
     *
     * @param type
     * @param excelList
     * @return
     */
    private ExcelResultDTO getExcelResultDTO(Integer type, List<List<String>> excelList, String tenantId, Boolean isReal) {
        LinkappTenant linkappTenant = linkappTenantMapper.getById(tenantId);

        ExcelResultDTO excelResultDTO = new ExcelResultDTO();
        //异常数据组织返回
        List<ExcelResultDetailDTO> excelResultDetailDTOS = new ArrayList<>();

        //=======定义必填字段的索引===========
        int nameIndex = isReal ? 2 : 0;
        int genderIndex = isReal ? 3 : 1;
        int nationIndex = isReal ? 4 : 2;
        int cardIndex = isReal ? 7 : 3;
        int telephoneIndex = isReal ? 8 : 4;
        int companyNameIndex = isReal ? 11 : 5;
        int groupNameIndex = isReal ? 12 : 6;
        int workTypeIndex = isReal ? 13 : 7;
        //=======定义必填字段的索引===========


        //成功数据
        //重复数据
        //失败数据
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<EmpUserBaseDTO> empUserBaseDTOS = new ArrayList<>();
        Set<String> cardSet = new HashSet<>();
        //获取工种
        Map<String, String> workTypeMap = LobarUtils.getWorkTypeMap();
        for (int i = 0; i < excelList.size(); i++) {
            ExcelResultDetailDTO excelResultDetailDTO = new ExcelResultDetailDTO();
            //异常提示信息
            List<String> msgs = new ArrayList<>();
            List<String> list = excelList.get(i);
            //验证塞数据
            EmpUserBaseDTO empUserBaseDTO = new EmpUserBaseDTO();
            empUserBaseDTO.setRealSys(isReal ? 1 : 0);
            empUserBaseDTO.setEmployStatus(1);
            if (isReal) {
                empUserBaseDTO.setGateId(list.get(1).trim());
                if (StringUtils.isBlank(list.get(1))) {
                    msgs.add("工号为空");
                }
            }
            empUserBaseDTO.setName(list.get(nameIndex).trim());
            if (StringUtils.isBlank(list.get(nameIndex))) {
                msgs.add("姓名为空");
            }
            empUserBaseDTO.setGender(checkGender(list.get(genderIndex).trim(), msgs));
            empUserBaseDTO.setNation(checkNation(list.get(nationIndex).trim(), msgs));
            empUserBaseDTO.setCard(checkCard(list.get(cardIndex).trim(), msgs, cardSet));
            if (StringUtils.isNotBlank(empUserBaseDTO.getCard())) {
                String s = empUserBaseDTO.getCard();
                try {
                    empUserBaseDTO.setBirthday(format.parse(s.substring(6, 10) + "-" + s.substring(10, 12) + "-" + s.substring(12, 14)));
                } catch (ParseException e) {
                    throw new BusinessException("excel解析错误");
                }
            }
            empUserBaseDTO.setTelephone(checkTelephone(list.get(telephoneIndex).trim(), msgs));
            UserProjectDTO userProject = new UserProjectDTO();
            userProject.setUserName(empUserBaseDTO.getName());
            userProject.setGateStatus(isReal ? 1 : 0);

            userProject.setGender(empUserBaseDTO.getGender());
            userProject.setBirthday(empUserBaseDTO.getBirthday());
            userProject.setGroupId(checkCompanyAndGroup(list.get(companyNameIndex).trim(), list.get(groupNameIndex).trim(), msgs, tenantId));
            userProject.setWorkType(checkWorkType(list.get(workTypeIndex).trim(), msgs, workTypeMap));
            userProject.setIsGroupLeader(0);
            userProject.setType("2");
            userProject.setTenantId(tenantId);
            userProject.setRealSys(isReal ? 1 : 0);
            empUserBaseDTO.setUserProject(userProject);

            excelResultDetailDTO.setNo(i + (isReal ? 2 : 3));
            excelResultDetailDTO.setName(empUserBaseDTO.getName());

            //进场时间处理
            empUserBaseDTO.setEmployTime(new Date());
            userProject.setStatus(1);
            if (isReal) {
                String joinS = list.get(14).trim();
                String outS = list.get(15).trim();
                Date join = checkTime(msgs, joinS, 1);
                Date out = checkTime(msgs, outS, 2);
                empUserBaseDTO.setEmployTime(join);
                userProject.setLeaveTime(out);
                if (null != join && null == out) {
                    userProject.setStatus(1);
                } else {
                    userProject.setStatus(0);
                    Date time = linkappTenant.getActualStartTime();
                    if (null == join) {
                        empUserBaseDTO.setEmployTime(time == null ? new Date() : time);
                    }
                    if (null == out) {
                        userProject.setLeaveTime(time == null ? new Date() : time);
                    }
                }

//        if (StringUtils.isBlank(joinS)){
//          if (StringUtils.isNotBlank(outS)){
//            msgs.add("请填写进场时间");
//          }
//        }else {
//          Date join = checkTime(msgs, joinS, 1);
//          Date out = checkTime(msgs, outS, 2);
//          if (null != join){
//              empUserBaseDTO.setEmployTime(join);
//              if (null != out){
//                userProject.setLeaveTime(out);
//                userProject.setStatus(0);
//                if (join.getTime() > out.getTime()){
//                  msgs.add("进场时间必须小于或等于退场时间");
//                }
//              }else {
//                userProject.setStatus(1);
//              }
//          }
//        }
            }
            userProject.setJoinTime(empUserBaseDTO.getEmployTime());

            //判断用户是否已在其他项目在场
            List<UserProject> userProjects = new ArrayList<>();
            if (StringUtils.isNotBlank(empUserBaseDTO.getCard())) {
                userProjects = userProjectMapper.selectByCard(empUserBaseDTO.getCard());
            }
//      long count = userProjects.stream().filter(
//          u -> Integer.valueOf(1).equals(u.getStatus())
//              && !tenantId.equals(u.getTenantId())
//              && Integer.valueOf(1).equals(u.getDeleteState()))
//          .count();
//      if (count > 0){
//        msgs.add("用户已任职其他项目");
//      }
            //失败数据
            if (msgs.size() > 0) {
                excelResultDetailDTO.setDetail(StringUtils.join(msgs, ","));
                excelResultDetailDTO.setType(1);
                excelResultDetailDTO.setTypeName("失败");
            } else {
                //重复数据
                //查询花名册是否重复
                long count1 = userProjects.stream().filter(u -> tenantId.equals(u.getTenantId())
                        && Integer.valueOf(1).equals(u.getDeleteState())).count();
                if (count1 > 0) {
                    if (!Integer.valueOf(1).equals(type)) {
                        excelResultDetailDTO.setDetail("人员重复");
                        excelResultDetailDTO.setType(2);
                        excelResultDetailDTO.setTypeName("重复");
                        excelResultDetailDTOS.add(excelResultDetailDTO);
                        continue;
                    } else {
                        ExcelResultDetailDTO repeat = new ExcelResultDetailDTO();
                        repeat.setName(excelResultDetailDTO.getName());
                        repeat.setNo(excelResultDetailDTO.getNo());
                        repeat.setDetail("人员信息覆盖");
                        repeat.setType(2);
                        repeat.setTypeName("覆盖");
                        excelResultDetailDTOS.add(repeat);
                    }
                }
                //下发闸机不做检验了 20220920
//        userProject.setGateStatus(0);
                //未下发闸机数据
//        String userPhoto = this.getUserPhoto(empUserBaseDTO.getCard(),tenantId);

                //闸机验证去掉  2022 10 21
//        Map<String, Object> map = this.getUserPhoto(empUserBaseDTO.getGateId(), tenantId);
//        Boolean flag = (Boolean)map.get("flag");
//        if (!flag){
//          excelResultDetailDTO.setDetail("未下发闸机权限");
//          excelResultDetailDTO.setType(3);
//          excelResultDetailDTO.setTypeName("未下发闸机权限");
//        }else{
//          userProject.setGateStatus(1);
//          String userPhoto = (String)map.get("result");
//          if (StringUtils.isNotBlank(userPhoto)){
//            empUserBaseDTO.setPhoto(ossService.saveImgBase64(userPhoto,
//                empUserBaseDTO.getName() + "photo.png"));
//            userProject.setPhoto(empUserBaseDTO.getPhoto());
//          }
//        }


                empUserBaseDTOS.add(empUserBaseDTO);
            }
            excelResultDetailDTOS.add(excelResultDetailDTO);
        }
        //汇总
        excelResultDTO.setSum(excelList.size());
        excelResultDTO.setSuccess(empUserBaseDTOS.size());
        List<ExcelResultDetailDTO> repeat = excelResultDetailDTOS.stream()
                .filter(e -> Integer.valueOf(2).equals(e.getType())).collect(Collectors.toList());
        excelResultDTO.setRepeat(repeat.size());
        List<ExcelResultDetailDTO> fail = excelResultDetailDTOS.stream()
                .filter(e -> Integer.valueOf(1).equals(e.getType())).collect(Collectors.toList());
        excelResultDTO.setFail(fail.size());
        List<ExcelResultDetailDTO> notIssued = excelResultDetailDTOS.stream()
                .filter(e -> Integer.valueOf(3).equals(e.getType())).collect(Collectors.toList());
        excelResultDTO.setNotIssued(notIssued.size());
        //去掉类型为空的
        excelResultDetailDTOS.removeIf(e -> null == e.getType());
        excelResultDTO.setExcelResultDetailDTOS(excelResultDetailDTOS);

        //保存数据
        insertList(empUserBaseDTOS, type);
        return excelResultDTO;
    }

    private Date checkTime1(List<String> msgs, String time, Integer type) {
        String s = type == 1 ? "进" : "退";
        Date date = null;
        if (StringUtils.isNotBlank(time)) {
            //检验时间
            try {
                date = DateUtil.parse(time);
                if (date.getTime() > System.currentTimeMillis()) {
                    msgs.add(s + "场时间应该小于或等于当前时间");
                }
            } catch (Exception e) {
                msgs.add(s + "场时间格式错误");
            }
        }
        return date;
    }

    private Date checkTime(List<String> msgs, String time, Integer type) {
        String s = type == 1 ? "进" : "退";
        Date date = null;
        if (StringUtils.isNotBlank(time)) {
            //检验时间
            try {
                date = DateUtil.parse(time);
            } catch (Exception e) {
                msgs.add(s + "场时间格式错误");
            }
        }
        return date;
    }

    /**
     * app获取总人数和出勤率
     */
    @Override
    public LobarUserDTO getSum(String tenantId) {
        QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(tenantId)) {
            queryWrapper.eq("tenant_id_", tenantId);
        }
        queryWrapper.eq("status_", 1).eq("delete_state_", 1);
        List<UserProject> projects = userProjectMapper.selectList(queryWrapper);
        int size = projects.stream().map(p -> p.getUserId()).collect(Collectors.toList()).size();
        LobarUserDTO lobarUserDTO = new LobarUserDTO();
        lobarUserDTO.setSum(size);
        lobarUserDTO.setRequired(size);
//    lobarUserDTO.setSum(projects.size());
//    lobarUserDTO.setRequired(projects.size());
        //管理人员
        List<String> managerUserIds = projects.stream()
                .filter(p -> StringUtils.isNotBlank(p.getWorkType()) && p.getWorkType().startsWith("管理人员"))
                .map(UserProject::getUserId).collect(Collectors.toList());
        lobarUserDTO.setManager(managerUserIds.size());
        lobarUserDTO.setManagerUserIds(managerUserIds);
        //作业人员
        List<String> workUserIds = projects.stream()
                .filter(p -> StringUtils.isNotBlank(p.getWorkType()) && p.getWorkType().startsWith("作业人员"))
                .map(UserProject::getUserId).collect(Collectors.toList());
        lobarUserDTO.setWork(workUserIds.size());
        lobarUserDTO.setWorkUserIds(workUserIds);
        //其他人员
        List<String> otherUserIds = projects.stream()
                .filter(p -> StringUtils.isBlank(p.getWorkType()) || p.getWorkType().startsWith("其他人员"))
                .map(UserProject::getUserId).collect(Collectors.toList());
        lobarUserDTO.setOther(otherUserIds.size());
        lobarUserDTO.setOtherUserIds(otherUserIds);

        //考勤
        QueryWrapper<UserRecord> recordQueryWrapper = new QueryWrapper<>();
        recordQueryWrapper.eq("record_time_", DateUtil.beginOfDay(new Date()))
                .ne("record_type_", 0);
        if (StringUtils.isNotBlank(tenantId)) {
            recordQueryWrapper.eq("tenant_id_", tenantId);
        }
        Integer integer = userRecordMapper.selectCount(recordQueryWrapper);
        lobarUserDTO.setAttendance(integer);
        lobarUserDTO.setPart(PercentageUtils.computePercentOne(lobarUserDTO.getAttendance(), lobarUserDTO.getSum()));
        return lobarUserDTO;
    }

    @Override
    public Map<String, List<LobarUserDTO>> getBy3WorkType(String workType) {
        Map<String, List<LobarUserDTO>> map = new HashMap<>();
        List<UserProject> userProjects = this.getByWorkType(workType);
        Map<String, List<UserProject>> listMap = userProjects.stream().filter(u -> StringUtils.isNotBlank(u.getWorkType())).collect(Collectors.groupingBy(
                u -> u.getWorkType()
                        .substring(u.getWorkType().indexOf("/") + 1, u.getWorkType().lastIndexOf("/"))));
        listMap.forEach((k, v) -> {
            List<LobarUserDTO> lobarUserDTOS = new ArrayList<>();
            //第三级再分组
            Map<String, List<UserProject>> sonMap = v.stream().filter(u -> StringUtils.isNotBlank(u.getWorkType()))
                    .collect(Collectors.groupingBy(c -> c.getWorkType()
                            .substring(c.getWorkType().lastIndexOf("/") + 1)));
            sonMap.forEach((key, value) -> {
                LobarUserDTO lobarUserDTO = new LobarUserDTO();
                lobarUserDTO.setName(key);
                //出勤人数
                long count = value.stream().filter(va -> StringUtils.isNotBlank(va.getId())).count();
                lobarUserDTO.setAttendance((int) count);
                lobarUserDTO.setPart(PercentageUtils.computePercentOne((int) count, value.size()));
                lobarUserDTOS.add(lobarUserDTO);
            });
            map.put(k, lobarUserDTOS);
        });
        return map;
    }

    @Override
    public List<LobarUserDTO> getBy2WorkType(String workType) {
        List<UserProject> userProjects = this.getByWorkType(workType);
        List<LobarUserDTO> lobarUserDTOS = new ArrayList<>();
        //第三级再分组
        Map<String, List<UserProject>> sonMap = userProjects.stream().filter(u -> StringUtils.isNotBlank(u.getWorkType()))
                .collect(Collectors.groupingBy(c -> c.getWorkType()
                        .substring(c.getWorkType().lastIndexOf("/") + 1)));
        sonMap.forEach((key, value) -> {
            LobarUserDTO lobarUserDTO = new LobarUserDTO();
            lobarUserDTO.setName(key);
            //出勤人数
            long count = value.stream().filter(va -> StringUtils.isNotBlank(va.getId())).count();
            lobarUserDTO.setAttendance((int) count);
            lobarUserDTO.setPart(PercentageUtils.computePercentOne((int) count, value.size()));
            lobarUserDTOS.add(lobarUserDTO);
        });
        return lobarUserDTOS;
    }

    /**
     * 获取工种考勤率
     */
    public List<UserProject> getByWorkType(String workType) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        List<UserProject> userProjects = userProjectMapper.getRecordByWorkType(tenantId, workType);
        return userProjects;
    }

    /**
     * 导入数据插入
     *
     * @param empUserBaseDTOS
     * @param type
     */
    private void insertList(List<EmpUserBaseDTO> empUserBaseDTOS, Integer type) {
        empUserBaseDTOS.forEach(e -> {
            //查询花名册池是否重复
            QueryWrapper<EmpUserBase> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("card_", e.getCard());
            List<EmpUserBase> userBases = empUserBaseMapper.selectList(queryWrapper);
            //查询花名册是否重复
            List<UserProject> userProjects = userProjectMapper.selectByCard(e.getCard());
            userProjects = userProjects.stream().filter(u -> e.getUserProject().getTenantId().equals(u.getTenantId()))
                    .collect(Collectors.toList());
            //设置基本属性
            if (Integer.valueOf(1).equals(type)) {
                this.setBaseEmp(e);
                //分开保存
                EmpUserBase empUserBase = new EmpUserBase();
                BeanUtils.copyProperties(e, empUserBase);
                if (null != userBases && userBases.size() > 0) {
                    empUserBase.setId(userBases.get(0).getId());
                    empUserBaseMapper.update(null, getEmpWrapper(empUserBase));
                } else {
                    empUserBaseMapper.insert(empUserBase);
                }

                //同步到emp
                syncUser(empUserBase, e.getUserProject().getTenantId());
                e.getUserProject().setUserId(empUserBase.getId());
                //添加当天当成入场时间
                if (null == e.getUserProject()) {
                    e.getUserProject().setJoinTime(new Date());
                }
                if (null != userProjects && userProjects.size() > 0) {
                    UserProject old = userProjects.get(0);
                    //判斷用户此前是否是班组长
                    if (Integer.valueOf(1).equals(old.getIsGroupLeader())) {
                        //设置前班组组长为null
                        UpdateWrapper<Group> groupUpdateWrapper = new UpdateWrapper<>();
                        groupUpdateWrapper.set("lead_user_id_", null)
                                .eq("id", old.getGroupId());
                        groupMapper.update(null, groupUpdateWrapper);
                    }
                    e.getUserProject().setId(old.getId());
                    e.getUserProject().setDeleteState(1);
                    baseMapper.update(null, getUserWrapper(e.getUserProject()));
//          baseMapper.updateById(e.getUserProject());
                } else {
                    baseMapper.insert(e.getUserProject());
                }
            } else {
                if (null != userBases && userBases.size() > 0) {
                    e.setId(userBases.get(0).getId());
                    e.getUserProject().setUserName(userBases.get(0).getName());
                    e.getUserProject().setPhoto(userBases.get(0).getPhoto());
                    e.getUserProject().setBirthday(userBases.get(0).getBirthday());
                    e.getUserProject().setGender(userBases.get(0).getGender());
                    this.setBaseEmp(e);
                } else {
                    EmpUserBase empUserBase = new EmpUserBase();
                    BeanUtils.copyProperties(e, empUserBase);
                    this.setBaseEmp(e);
                    //同步到emp
                    syncUser(empUserBase, e.getUserProject().getTenantId());
                    empUserBaseMapper.insert(empUserBase);
                    e.setId(empUserBase.getId());
                }
                e.getUserProject().setUserId(e.getId());
                //删除之前添加过的
                QueryWrapper<UserProject> deQqueryWrapper = new QueryWrapper<>();
                deQqueryWrapper.eq("user_id_", e.getUserProject().getUserId())
                        .eq("tenant_id_", linkappUserContextProducer.getNotNullCurrent().getTenantId());
                baseMapper.delete(deQqueryWrapper);
                baseMapper.insert(e.getUserProject());
            }

            //同步到东西湖智慧工地
            // 创建线程池
            ExecutorService executorService = Executors.newFixedThreadPool(20);
            CompletableFuture.supplyAsync(() -> {
                        syncToSystem(e, 0);
                        return null;
                    }, executorService);
        });
    }

    /**
     * 拼凑用户更新条件
     *
     * @param userProject
     * @return
     */
    private Wrapper<UserProject> getUserWrapper(UserProject userProject) {
        UpdateWrapper<UserProject> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("user_name_", userProject.getUserName())
                .set("gender_", userProject.getGender())
                .set("no_", null)
                .set("work_type_", userProject.getWorkType())
                .set("is_group_leader_", userProject.getIsGroupLeader())
                .set("join_time_", userProject.getJoinTime())
                .set("leave_time_", userProject.getLeaveTime())
                .set("status_", userProject.getStatus())
                .set("gate_status_", userProject.getGateStatus())
                .set("birthday_", userProject.getBirthday())
                .set("photo_", userProject.getPhoto())
                .set("group_id_", userProject.getGroupId())
                .set("type_", userProject.getType())
                .set("creator_id_", userProject.getCreatorId())
                .set("create_time_", userProject.getCreateTime())
                .set("modify_id_", userProject.getModifyId())
                .set("modify_time_", userProject.getModifyTime())
                .set("delete_state_", userProject.getDeleteState())
                .set("real_sys_", userProject.getRealSys())
                .eq("id", userProject.getId());
        return updateWrapper;
    }

    /**
     * 拼凑更新条件
     *
     * @param empUserBase
     * @return
     */
    private UpdateWrapper<EmpUserBase> getEmpWrapper(EmpUserBase empUserBase) {
        UpdateWrapper<EmpUserBase> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("name_", empUserBase.getName())
                .set("gender_", empUserBase.getGender())
                .set("telephone_", empUserBase.getTelephone())
                .set("education_", null)
                .set("nation_", empUserBase.getNation())
                .set("degree_", null)
                .set("birthday_", empUserBase.getBirthday())
                .set("card_type_", null)
                .set("card_", empUserBase.getCard())
                .set("authority_", null)
//        .set("photo_",empUserBase.getPhoto())
//        .set("card_a_",null)
                .set("employ_time_", empUserBase.getEmployTime())
                .set("employ_status_", empUserBase.getEmployStatus())
                .set("creator_id_", empUserBase.getCreatorId())
                .set("create_time_", empUserBase.getCreateTime())
                .set("modify_id_", empUserBase.getModifyId())
                .set("modify_time_", empUserBase.getModifyTime())
                .set("gate_id_", empUserBase.getGateId())
                .set("real_sys_", empUserBase.getRealSys())
                .eq("id", empUserBase.getId());
        return updateWrapper;
    }

    /**
     * 验证民族
     *
     * @param s
     * @param msgs
     * @return
     */
    private String checkNation(String s, List<String> msgs) {
        String result = null;
        if (StringUtils.isNotBlank(s)) {
            String aNative = LobarUtils.getNative(s);
            if (StringUtils.isBlank(aNative)) {
                msgs.add("民族填写错误");
            } else {
                result = aNative;
            }
        }
        return result;
    }

    /**
     * 验证工种
     *
     * @param workType
     * @param msgs
     * @param workTypeMap
     * @return
     */
    private String checkWorkType(String workType, List<String> msgs,
                                 Map<String, String> workTypeMap) {
        String result = null;
        if (StringUtils.isBlank(workType)) {
            msgs.add("工种为空");
        } else {
            String type = workTypeMap.get(workType);
            if (StringUtils.isBlank(type)) {
                msgs.add("没有对应的工种");
            } else {
                result = type;
            }
        }
        return result;
    }

    /**
     * 验证参建单位和班组
     *
     * @param company
     * @param group
     * @param msgs
     * @return
     */
    private String checkCompanyAndGroup(String company, String group, List<String> msgs, String tenantId) {
        String result = null;
        if (StringUtils.isBlank(company)) {
            msgs.add("参建单位为空");
        }
        if (StringUtils.isBlank(group)) {
            msgs.add("班组为空");
        }
        if (StringUtils.isNotBlank(company)) {
            //查询参建单位是否存在
            List<LaborCompanyProject> companyProjects = laborCompanyProjectMapper.findCompanyByName(company, tenantId);
            if (null != companyProjects && companyProjects.size() > 0) {
                String id = companyProjects.get(0).getId();
                //查询班组
                QueryWrapper<Group> queryWrapper = new QueryWrapper<>();
                QueryWrapper<Group> wrapper = queryWrapper.eq("tenant_id_", tenantId)
                        .eq("company_project_id_", id)
                        .eq("name_", group);
                List<Group> groupList = groupMapper.selectList(wrapper);
                if (null != groupList && groupList.size() > 0) {
                    result = groupList.get(0).getId();
                } else {
                    msgs.add("参建单位下没有对应的班组");
                }
            } else {
                msgs.add("参建单位不存在");
            }
        }
        return result;
    }

    /**
     * 验证手机号码
     *
     * @param s
     * @param msgs
     * @return
     */
    private String checkTelephone(String s, List<String> msgs) {
        String tel = null;
        if (StringUtils.isBlank(s)) {
            msgs.add("联系电话为空");
        } else {
            Pattern pattern = Pattern.compile("[0-9]*");
            Matcher isNum = pattern.matcher(s);
            if (!isNum.matches() || s.length() != 11) {
                msgs.add("联系电话格式错误");
            } else {
                tel = s;
            }
        }
        return tel;
    }

    /**
     * 验证身份证
     *
     * @param s
     * @param msgs
     * @param cardSet 身份证集合
     * @return
     */
    private String checkCard(String s, List<String> msgs, Set<String> cardSet) {
        String card = null;
        //校验是否存在黑名单中
        if (StringUtils.isBlank(s)) {
            msgs.add("身份证为空");
        }else if(userBlacklistMapper.countByCard(s)>0){
            msgs.add("该身份证已被加入黑名单");
        } else if (!IdentityUtils.isLegalPattern(s)) {
            msgs.add("身份证格式错误");
        } else if (cardSet.contains(s)) {
            msgs.add("与表格中身份证数据重复");
        } else {
            card = s;
            cardSet.add(s);
        }
        return card;
    }

    /**
     * 验证性别
     *
     * @param s
     * @param msgs
     */
    private Integer checkGender(String s, List<String> msgs) {
        Integer gender = null;
        if (StringUtils.isBlank(s)) {
            msgs.add("性别为空");
        } else if (!"男".equals(s) && !"女".equals(s)) {
            msgs.add("性别填写错误");
        } else {
            gender = "男".equals(s) ? 1 : 2;
        }
        return gender;
    }

    private void checkExistEmp(EmpUserBaseDTO empUserBaseDTO) {
        //存在即设置id
        if (StringUtils.isBlank(empUserBaseDTO.getId())) {
            QueryWrapper<EmpUserBase> queryWrapper = new QueryWrapper<>();
            //判断重复条件
            queryWrapper.eq("card_", empUserBaseDTO.getCard());
            List<EmpUserBase> empUserBases = empUserBaseMapper.selectList(queryWrapper);
            if (empUserBases.size() > 0) {
                empUserBaseDTO.setId(empUserBases.get(0).getId());
            }
            //判断是否存在黑名单，如果存在，不让添加
            if (null != empUserBaseDTO.getId()) {
                QueryWrapper<UserBlacklist> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("user_id_", empUserBaseDTO.getId());
                queryWrapper1.in("approval_status_", 0,1);
                List<UserBlacklist> userBlacklists = userBlacklistMapper.selectList(queryWrapper1);
                if (CollectionUtil.isNotEmpty(userBlacklists)) {
                    throw new BusinessException("该用户已存在黑名单中，无法添加");
                }
            }
        }
    }

    @Override
    public IPage<UserProjectDTO> queryListByPage(RequestModel<UserProjectDTO> requestModel) {
        Page page = requestModel.getPage();
        UserProjectDTO userProjectDTO = requestModel.getCustomQueryParams();
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            userProjectDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        //if blackFlag = 0
        //如果严格按照userIds过滤，则不用管黑名单情况
        if(null == userProjectDTO.getBlackFlag() && !Boolean.TRUE.equals(userProjectDTO.getAllFlag())){
            userProjectDTO.setBlackFlag(0);
        }
        if (null != userProjectDTO.getBlackFlag()) {
            //查询所有黑名单人员id
            QueryWrapper<UserBlacklist> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("approval_status_",0,1);
            List<UserBlacklist> userBlacklists = userBlacklistMapper.selectList(queryWrapper);
            List<String> notUserIds = userBlacklists.stream().map(u -> u.getUserId())
                    .collect(Collectors.toList());
            if (Integer.valueOf(0).equals(userProjectDTO.getBlackFlag())) {
                userProjectDTO.setNotUserIds(notUserIds);
            } else {
                userProjectDTO.setUserIds(notUserIds);
            }
        }
        IPage<UserProjectDTO> userProjectIPage = baseMapper.queryListByPage(page, userProjectDTO);
        //计算年龄
        userProjectIPage.getRecords().forEach(g -> {
            Date birthday = g.getBirthday();
            int age = DateUtil.age(birthday, new Date());
            g.setAge(age);
        });
        return userProjectIPage;
    }

    /**
     * 验证重复
     */
    private void checkExist(UserProject userProject) {
        //查询旧数据
        UserProject old = baseMapper.selectById(userProject.getId());
        if (Integer.valueOf(1).equals(userProject.getStatus())) {
            if (Integer.valueOf(0).equals(old.getStatus())) {
                if (null == userProject.getJoinTime()) {
                    userProject.setJoinTime(new Date());
                }
//        //查询改人员是否入职其他项目
//        QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("user_id_", old.getUserId());
//        queryWrapper.eq("status_", userProject.getStatus());
//        Integer integer = baseMapper.selectCount(queryWrapper);
//        if (integer > 0) {
//          throw new BusinessException("用户已任职其他项目");
//        }
                //查询其所属班组是否退场
                Group group = groupMapper.selectById(old.getGroupId());
                if (Integer.valueOf(0).equals(group.getStatus())) {
                    throw new BusinessException("用户所属班组已退场");
                }
            }
        } else if (Integer.valueOf(1).equals(old.getStatus())) {
            userProject.setLeaveTime(new Date());
        }
    }

    /**
     * 设置基本属性
     *
     * @param userProject
     */
    private void setBase(UserProject userProject) {
        userProject.setModifyTime(new Date());
        userProject.setModifyId(linkappUserContextProducer.getCurrent().getId());
        //没有id就是新增,有就是编辑
        if (StringUtils.isBlank(userProject.getId())) {
            userProject.setCreatorId(linkappUserContextProducer.getCurrent().getId());
            userProject.setCreateTime(new Date());
            userProject.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
    }

    /**
     * 设置基本属性
     * flag true就是新增使用
     *
     * @param empUserBaseDTO
     */
    private void setBaseEmp(EmpUserBaseDTO empUserBaseDTO) {
        empUserBaseDTO.setModifyTime(new Date());
        if (null != linkappUserContextProducer.getCurrent()) {
            empUserBaseDTO.setModifyId(linkappUserContextProducer.getCurrent().getId());
            empUserBaseDTO.getUserProject().setModifyId(linkappUserContextProducer.getCurrent().getId());
        }
        empUserBaseDTO.getUserProject().setModifyTime(new Date());
        //没有id就是新增,有就是编辑
        if (StringUtils.isBlank(empUserBaseDTO.getId())) {
            empUserBaseDTO.getUserProject().setCreateTime(new Date());
            if (null != linkappUserContextProducer.getCurrent()) {
                if (null == empUserBaseDTO.getCreatorId()) {
                    empUserBaseDTO.setCreatorId(linkappUserContextProducer.getCurrent().getId());
                }
            }
            if (null == empUserBaseDTO.getCreateTime()) {
                empUserBaseDTO.setCreateTime(new Date());
            }
            //设置一些默认属性
            if (null == empUserBaseDTO.getEmployStatus()) {
                empUserBaseDTO.setEmployStatus(1);
            }
        }
        if (StringUtils.isBlank(empUserBaseDTO.getUserProject().getId())) {
            empUserBaseDTO.getUserProject().setCreateTime(new Date());
            if (null != linkappUserContextProducer.getCurrent()) {
                empUserBaseDTO.getUserProject().setCreatorId(linkappUserContextProducer.getCurrent().getId());
            }
            if (StringUtils.isBlank(empUserBaseDTO.getUserProject().getTenantId())) {
                if (null != linkappUserContextProducer.getCurrent()){
                    empUserBaseDTO.getUserProject().setTenantId(linkappUserContextProducer.getCurrent().getTenantId());
                }
            }
            if (null == empUserBaseDTO.getUserProject().getStatus()) {
                empUserBaseDTO.getUserProject().setStatus(1);
            }
        }
        //入职时间不填写，默认当天
        if (null == empUserBaseDTO.getUserProject().getJoinTime()) {
            empUserBaseDTO.setEmployTime(new Date());
        } else {
            empUserBaseDTO.setEmployTime(empUserBaseDTO.getUserProject().getJoinTime());
        }

        this.handleDTOBase64Pic(empUserBaseDTO);
        //冗余属性处理
        empUserBaseDTO.getUserProject().setUserName(empUserBaseDTO.getName());
        empUserBaseDTO.getUserProject().setPhoto(empUserBaseDTO.getPhoto());
        empUserBaseDTO.getUserProject().setBirthday(empUserBaseDTO.getBirthday());
        empUserBaseDTO.getUserProject().setGender(empUserBaseDTO.getGender());
    }


    /**
     * 处理 DTO 中图片问题，关于 base64 图片的处理，上传到 oss， 并返回相应的 路径地址
     *
     * @param empUserBaseDTO
     * @return
     */
    private EmpUserBaseDTO handleDTOBase64Pic(EmpUserBaseDTO empUserBaseDTO) {
        String photo = empUserBaseDTO.getPhoto(); // 临时图
        String cardA = empUserBaseDTO.getCardA(); // 身份证正面
        String cardB = empUserBaseDTO.getCardB(); // 身份证反面

        if (StringUtils.isNotEmpty(photo) && photo.startsWith("data:")) {
            String s = ossService.saveImgBase64(empUserBaseDTO.getPhoto(),
                    empUserBaseDTO.getName() + "photo.png");
            empUserBaseDTO.setPhoto(s);
        }

        if (StringUtils.isNotEmpty(cardA) && cardA.startsWith("data:")) {
            String s = ossService.saveImgBase64(empUserBaseDTO.getCardA(),
                    empUserBaseDTO.getName() + "cardA.png");
            empUserBaseDTO.setCardA(s);
        }

        if (StringUtils.isNotEmpty(cardB) && cardB.startsWith("data:")) {
            String s = ossService.saveImgBase64(empUserBaseDTO.getCardB(),
                    empUserBaseDTO.getName() + "cardB.png");
            empUserBaseDTO.setCardB(s);
        }

        return empUserBaseDTO;
    }

    //下发到闸机
    @Override
    public Map<String, Object> userToGate(EmpUserBase empUserBase, Integer roleType) {
        Map<String, Object> map = new HashMap<>();
        List<String> codeList = new ArrayList<>();
        List<String> names = new ArrayList<>();

        //没有照片直接失败
        if (StringUtils.isBlank(empUserBase.getPhoto())) {
            //是否直接抛异常
            map.put("show", true);
            map.put("flag", false);
            map.put("msg", "下发失败，没有近期照片");
            return map;
        }


        QueryWrapper<Gate> queryWrapper = new QueryWrapper<>();
        //下发闸机需要查询班组对应
        if (Integer.valueOf(1).equals(roleType)) {
            //查询班组对应区域的闸机
            if (StringUtils.isNotBlank(empUserBase.getGroupId())) {
                Group group = groupMapper.selectById(empUserBase.getGroupId());
                if (null != group && StringUtils.isNotBlank(group.getServiceArea())) {
                    String[] split = group.getServiceArea().split(",");
                    List<Integer> list = Arrays.stream(split).map(s -> Integer.valueOf(s))
                            .collect(Collectors.toList());
                    queryWrapper.in("service_area", list);
                }
            } else {
                //是否直接抛异常
                map.put("show", true);
                map.put("flag", false);
                map.put("msg", "班组没有设置对应区域,人员无法下发闸机");
                return map;
            }
        }
        //查询已绑定编号的闸机
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        queryWrapper.eq("tenant_id_", tenantId)
                .isNotNull("code_").like("access_", 1);
        List<Gate> gates = gateMapper.selectList(queryWrapper);
        Set<String> codeSet = gates.stream().map(g -> g.getCode()).collect(Collectors.toSet());
        AtomicBoolean flag = new AtomicBoolean(true);
        if (null != codeSet && codeSet.size() > 0) {
            //查询在不在设备库里
            List<Device> devices = deviceMapper.findDeviceByCodesGlobal(codeSet, tenantId);
            Set<String> codes = devices.stream().map(g -> g.getCode()).collect(Collectors.toSet());
            if (null == codes || codes.size() < 1) {
                flag.set(false);
                names.add("没有绑定到真实设备的闸机");
            }
            codes.forEach(code -> {
                List<Gate> newGates = gates.stream().filter(g -> code.equals(g.getCode()))
                        .collect(Collectors.toList());
                //先查询闸机中有没有
                QueryWrapper<UserGateLink> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("user_id_", empUserBase.getId())
                        .eq("tenant_id_", tenantId).eq("gate_id_", newGates.get(0).getId());
                List<UserGateLink> gateLinks = userGateLinkMapper.selectList(queryWrapper1);
                UserGateLink userGateLink = null;
                boolean insertFlag = false;
                if (gateLinks.size() > 0) {
                    userGateLink = gateLinks.get(0);
                } else {
                    userGateLink = new UserGateLink();
                    userGateLink.setModifyTime(new Date());
                    userGateLink.setCreateTime(new Date());
                    userGateLink.setTenantId(tenantId);
                    userGateLink.setGateId(newGates.get(0).getId());
                    userGateLink.setUserId(empUserBase.getId());
                    userGateLinkMapper.insert(userGateLink);
                    insertFlag = true;
                }
                //先删除
//        delGate(empUserBase, code);
                //后更新
                Map<String, Object> downParameter = new HashMap<>();
                //设备编号
                downParameter.put("device_id", code);
                //parameter 参数 id身份证 role 1白名单  regImage照片
                //parameter: {id: "213", name: "张三", role: 1, regImage: "11"}
                Map<String, Object> parameter = new HashMap<>();
//        parameter.put("id",empUserBase.getGateId());
                //组织id
                //id要生成 定义id
                String idPre = Gate.getIdPre();
                parameter.put("id", idPre + userGateLink.getId());
                parameter.put("idCard", empUserBase.getCard());
                parameter.put("name", empUserBase.getName());
                parameter.put("role", roleType);
                parameter.put("regImage", empUserBase.getPhoto());
                downParameter.put("parameter", parameter);
                downParameter.put("service_id", "uploadPerson");
                downParameter.put("tenantId", tenantId);
                downParameter.put("userId", empUserBase.getId());
                downParameter.put("insertFlag", insertFlag);
                downParameter.put("gateId", newGates.get(0).getId());
                ApiDownResultDTO send = deviceServiceService.sendToGate(downParameter);
                if (!"0".equals(send.getCode())) {
                    //失败要删除关系
                    if (gateLinks.size() < 1) {
                        userGateLink.deleteById(userGateLink.getId());
                    }
                    codeList.add(code);
                    flag.set(false);
                    //添加失败的闸机名称
                    List<String> list = gates.stream().filter(g -> code.equals(g.getCode()))
                            .map(g -> g.getName()).collect(Collectors.toList());
                    names.addAll(list);
                }
//        else {
//          //保存id
//          String message = send.getMsg();
//          if (StringUtils.isNotBlank(message) && message.contains("id=")){
//            //处理流水信息
//            //处理msg
//            String id = message.substring(message.indexOf("id=") + 3, message.indexOf(")"));
//            if (StringUtils.isNotBlank(id) && !id.equals(empUserBase.getCard())){
//              //当id与card不一致时保存id
//              UpdateWrapper<EmpUserBase> updateWrapper = new UpdateWrapper<>();
//              updateWrapper.set("gate_id_",id)
//                  .eq("card_",empUserBase.getCard());
//              empUserBaseMapper.update(null,updateWrapper);
//            }
//          }
//        }
                if (names.size() > 0) {
                    List<String> list = gates.stream().map(g -> g.getName()).collect(Collectors.toList());
                    String s = "下发到绑定真实设备的闸机:" + StringUtils.join(list, "，");
                    map.put("msg", s + "。其中下发到以下闸机失败：" + StringUtils.join(names, "，"));
                }
            });
        } else {
            flag.set(false);
            names.add("没有符合条件(绑定真实设备,通行管理包含施工区)的闸机");
        }
        map.put("flag", flag.get());
        if (!map.containsKey("msg") && names.size() > 0) {
            map.put("msg", names.get(0));
        }
        map.put("codeList", codeList);
        return map;
    }

    /**
     * flag 为true 抛出异常
     *
     * @param empUserBase
     * @param code
     * @param flag
     */
    @Override
    public void delGate(EmpUserBase empUserBase, String code, Boolean flag) {
        Map<String, Object> downParameter = new HashMap<>();
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //查询关联关系
        QueryWrapper<Gate> gateQueryWrapper = new QueryWrapper<>();
        gateQueryWrapper.eq("tenant_id_", tenantId).eq("code_", code);
        List<Gate> gates = gateMapper.selectList(gateQueryWrapper);
        Map<String, Object> parameter = new HashMap<>();
        UserGateLink userGateLink = null;
        if (gates.size() > 0) {
            QueryWrapper<UserGateLink> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tenant_id_", tenantId)
                    .eq("user_id_", empUserBase.getId()).eq("gate_id_", gates.get(0).getId());
            List<UserGateLink> userGateLinks = userGateLinkMapper.selectList(queryWrapper);
            if (userGateLinks.size() > 0) {
                userGateLink = userGateLinks.get(0);
                String idPre = Gate.getIdPre();
                parameter.put("id", idPre + userGateLink.getId());
            } else {
                parameter.put("id", empUserBase.getCard());
            }
        }
        //设备编号
        downParameter.put("device_id", code);
        downParameter.put("parameter", parameter);
        downParameter.put("service_id", "delPerson");
        if (userGateLink != null) {
            downParameter.put("userGateLinkId", userGateLink.getId());
        }
        ApiDownResultDTO send = deviceServiceService.sendToGate(downParameter);
        if (!"0".equals(send.getCode())) {
            LOGGER.info("闸机:" + code + "删除失败");
            if (Boolean.TRUE.equals(flag)) {
                throw new BusinessException("删除失败, " + send.getMsg());
            }
        } else if (null != userGateLink) {
            userGateLinkMapper.deleteById(userGateLink.getId());
        }
    }

    /**
     * 实时人员统计（出勤/在场）
     */
    @Override
    public List<LobarUserDTO> getOmNumByTid(String tenantId) {
        //查询今天的
        LobarUserDTO sum = getSum(tenantId);
        //查询近7天的数据
        List<UserStatistics> sevenAttendance = userStatisticsMapper.findSevenAttendance(tenantId);

        //去重代码
//    List<UserRecord> recordList = userRecordMapper.findSevenAttendance(tenantId);
//    List<UserStatistics> sevenAttendance = new ArrayList<>();
//    Map<Date, List<UserRecord>> listMap = recordList.stream()
//        .collect(Collectors.groupingBy(r -> r.getRecordTime()));
//    listMap.forEach((k,v)->{
//      UserStatistics userStatistics = new UserStatistics();
//      userStatistics.setRecordTime(k);
//      int size = v.stream().map(va -> va.getUserId()).collect(Collectors.toSet()).size();
//      userStatistics.setSum(size);
//      int size1 = v.stream().filter(va -> !Integer.valueOf(0).equals(va.getRecordType()))
//          .map(va -> va.getUserId()).collect(Collectors.toSet()).size();
//      userStatistics.setOn(size1);
//      sevenAttendance.add(userStatistics);
//    });
        //组装数据
        List<LobarUserDTO> lobarUserDTOS = new ArrayList<>();
        for (int i = 6; i >= 0; i--) {
            LobarUserDTO lobarUserDTO = new LobarUserDTO();
            if (i == 0) {
                //当天数据
                lobarUserDTO.setRecordTime(new Date());
                lobarUserDTO.setSum(sum.getSum());
                lobarUserDTO.setAttendance(sum.getAttendance());
            } else {
                Calendar calendar = DateUtil.beginOfDay(Calendar.getInstance());
                calendar.add(Calendar.DAY_OF_YEAR, -i);
                List<UserStatistics> dtos = sevenAttendance.stream()
                        .filter(u -> u.getRecordTime().equals(calendar.getTime()))
                        .collect(Collectors.toList());
                if (dtos.size() > 0) {
                    lobarUserDTO.setAttendance(dtos.get(0).getOn());
                    lobarUserDTO.setSum(dtos.get(0).getSum());
                } else {
                    lobarUserDTO.setAttendance(0);
                    lobarUserDTO.setSum(0);
                }
                lobarUserDTO.setRecordTime(calendar.getTime());
            }
            lobarUserDTOS.add(lobarUserDTO);
        }
        return lobarUserDTOS;
    }

    /**
     * 下发到指定闸机
     *
     * @param gate
     * @param empUserBase
     * @return
     */
    @Override
    public ExcelResultDetailDTO userToOneGate(EmpUserBase empUserBase, Gate gate) {
        ExcelResultDetailDTO excelResultDetailDTO = new ExcelResultDetailDTO();
        excelResultDetailDTO.setTypeName(empUserBase.getGroupName() + "/" + empUserBase.getCompanyName());
        if (StringUtils.isBlank(empUserBase.getPhoto())) {
            excelResultDetailDTO.setType(1);
            excelResultDetailDTO.setName(empUserBase.getName());
            excelResultDetailDTO.setDetail("没有近期照片");
            return excelResultDetailDTO;
        }

        UserGateLink userGateLink = new UserGateLink();
        //先查询有没有下发过
        QueryWrapper<UserGateLink> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id_", gate.getTenantId())
                .eq("gate_id_", gate.getId())
                .eq("user_id_", empUserBase.getId());
        List<UserGateLink> gateLinks = userGateLinkMapper.selectList(queryWrapper);
        boolean insertFlag = false;
        if (gateLinks.size() > 0) {
            excelResultDetailDTO.setType(1);
            excelResultDetailDTO.setName(empUserBase.getName());
            excelResultDetailDTO.setDetail("下发闸机失败,该人员已经下发");
            return excelResultDetailDTO;
        } else {
            userGateLink.setModifyTime(new Date());
            userGateLink.setCreateTime(new Date());
            userGateLink.setTenantId(gate.getTenantId());
            userGateLink.setGateId(gate.getId());
            userGateLink.setUserId(empUserBase.getId());
            userGateLinkMapper.insert(userGateLink);
            insertFlag = true;
        }

        //后更新
        Map<String, Object> downParameter = new HashMap<>();
        //设备编号
        downParameter.put("device_id", gate.getCode());
        Map<String, Object> parameter = new HashMap<>();
        //id要生成 定义id
        String idPre = Gate.getIdPre();
        parameter.put("id", idPre + userGateLink.getId());
        parameter.put("idCard", empUserBase.getCard());
        parameter.put("name", empUserBase.getName());
        parameter.put("role", 1);
        parameter.put("regImage", empUserBase.getPhoto());
        downParameter.put("parameter", parameter);
        downParameter.put("service_id", "uploadPerson");
        downParameter.put("tenantId", gate.getTenantId());
        downParameter.put("gateId", gate.getId());
        downParameter.put("userId", empUserBase.getId());
        downParameter.put("insertFlag", insertFlag);
        ApiDownResultDTO send = deviceServiceService.sendToGate(downParameter);
        if (!"0".equals(send.getCode())) {
            excelResultDetailDTO.setType(1);
            excelResultDetailDTO.setName(empUserBase.getName());
            String s = "下发闸机失败";
            if (StringUtils.isNotBlank(send.getMsg())) {
                s += ": " + send.getMsg();
            }
            excelResultDetailDTO.setDetail(s);
            //失败了要删除保存的关系
            userGateLinkMapper.deleteById(userGateLink.getId());
        } else {
            excelResultDetailDTO.setType(6);
        }
        return excelResultDetailDTO;
    }

    /**
     * 批量导入人员近照
     */
    @Override
    public ExcelResultDTO importPhoto(List<UnzipFileVo> unzipFileVos, String tenantId, Integer type) throws Exception {
        ExcelResultDTO excelResultDTO = new ExcelResultDTO();
        CompletionService<ExcelResultDetailDTO> completionService = new ExecutorCompletionService(Executors.newFixedThreadPool(20));
        unzipFileVos.forEach(vo ->
                completionService.submit(() -> toCheckAndSave(type, tenantId, vo))
        );
        List<ExcelResultDetailDTO> sonList = new ArrayList<>();
        for (int i = 0; i < unzipFileVos.size(); i++) {
            ExcelResultDetailDTO excelResultDetailDTO = completionService.take().get();
            if (null != excelResultDetailDTO.getType()) {
                sonList.add(excelResultDetailDTO);
            }
        }
        excelResultDTO.setSum(unzipFileVos.size());
        long count = sonList.stream().filter(s -> Integer.valueOf(1).equals(s.getType())).count();
        excelResultDTO.setFail((int) count);
        excelResultDTO.setRepeat(sonList.size() - (int) count);
        excelResultDTO.setSuccess(unzipFileVos.size() - sonList.size());
        excelResultDTO.setSum(unzipFileVos.size());
        excelResultDTO.setExcelResultDetailDTOS(sonList);
        return excelResultDTO;
    }

    /**
     * @Description: 根据条件，分页(不分页)查询非黑名单人员
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public IPage<UserProjectDTO> queryEnListByPage(RequestModel<UserProjectDTO> requestModel) {
        Page page = requestModel.getPage();
        UserProjectDTO userProjectDTO = requestModel.getCustomQueryParams();
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            userProjectDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        IPage<UserProjectDTO> userProjectIPage = baseMapper.queryEnListByPage(page, userProjectDTO);
        //计算年龄
        userProjectIPage.getRecords().forEach(g -> {
            Date birthday = g.getBirthday();
            int age = 0;
            if (null != birthday) {
                age = DateUtil.age(birthday, new Date());
            }
            g.setAge(age);
        });
        return userProjectIPage;
    }

    /**
     * 查询最新的在岗人员
     *
     * @param userId
     * @return
     */
    @Override
    public UserProject findNew(String userId) {
        QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id_", userId).eq("delete_state_", 1)
                .orderByDesc("join_time_");
        List<UserProject> userProjects = userProjectMapper.selectList(queryWrapper);
        if (null != userProjects && userProjects.size() > 0) {
            //查询有没有在场的
            List<UserProject> onUsers = userProjects.stream()
                    .filter(u -> Integer.valueOf(1).equals(u.getStatus()))
                    .collect(Collectors.toList());
            if (onUsers.size() > 0) {
                return onUsers.get(0);
            } else {
                return userProjects.get(0);
            }
        }
        return new UserProject();
    }

    /**
     * @Description: 根据card查询是否存在base
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public EmpUserBase getByCard(String card) {
        QueryWrapper<EmpUserBase> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("card_", card);
        List<EmpUserBase> empUserBases = empUserBaseMapper.selectList(queryWrapper);
        if (empUserBases.size() > 0) {
            return empUserBases.get(0);
        }
        return null;
    }

    @Override
    public IPage<UserProjectDTO> queryBlackListByPage(RequestModel<UserProjectDTO> requestModel) {
        Page page = requestModel.getPage();
        UserProjectDTO userProjectDTO = requestModel.getCustomQueryParams();
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            userProjectDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        //if blackFlag = 0
        if (null != userProjectDTO.getBlackFlag()) {
            //查询所有黑名单人员id
            List<UserBlacklist> userBlacklists = userBlacklistMapper.selectList(new QueryWrapper<>());
            List<String> notUserIds = userBlacklists.stream().map(u -> u.getUserId())
                    .collect(Collectors.toList());
            if (Integer.valueOf(0).equals(userProjectDTO.getBlackFlag())) {
                userProjectDTO.setNotUserIds(notUserIds);
            } else {
                userProjectDTO.setUserIds(notUserIds);
            }
        }
        IPage<UserProjectDTO> userProjectIPage = baseMapper.queryBlackListByPage(page, userProjectDTO);
        return userProjectIPage;
    }

    /**
     * @Description: 根据条件，分页(不分页)查询人员在场情况
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public IPage<UserProjectDTO> onAreasList(RequestModel<UserProjectDTO> requestModel) {
        Page page = requestModel.getPage();
        UserProjectDTO userProjectDTO = requestModel.getCustomQueryParams();
        //项目id 过滤
        if (null != linkappUserContextProducer.getCurrent()) {
            userProjectDTO.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        }
        IPage<UserProjectDTO> userProjectIPage = baseMapper.onAreasList(page, userProjectDTO);
        return userProjectIPage;
    }

    /**
     * @Description: 在场人数统计
     * @author kan yuanfeng
     * @date 2020/11/04 11:42
     */
    @Override
    public Map<String, Integer> onAreaCount() {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        QueryWrapper<UserProject> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("delete_state_", 1)
                .eq("status_", 1)
                .eq("tenant_id_", linkappUserContextProducer.getNotNullCurrent().getTenantId())
                .in("on_area_", list);
        List<UserProject> userProjects = userProjectMapper.selectList(queryWrapper);
        //施工区
        long count1 = userProjects.stream().filter(u -> Integer.valueOf(1).equals(u.getOnArea()))
                .count();
        //办公区
        long count2 = userProjects.stream().filter(u -> Integer.valueOf(2).equals(u.getOnArea()))
                .count();
        //生活区
        long count3 = userProjects.stream().filter(u -> Integer.valueOf(3).equals(u.getOnArea()))
                .count();
        Map<String, Integer> map = new HashMap<>();
        map.put("1", (int) count1);
        map.put("2", (int) count2);
        map.put("3", (int) count3);
        return map;
    }

    @Override
    public void updateEduState(UserProject userProject) {
        LambdaUpdateWrapper<UserProject> userProjectLambdaUpdateWrapper = Wrappers.lambdaUpdate();
        userProjectLambdaUpdateWrapper.set(UserProject::getEduFlie, userProject.getEduFlie())
                .set(UserProject::getEduState, userProject.getEduState());
        userProjectLambdaUpdateWrapper.eq(UserProject::getId, userProject.getId());
        userProjectMapper.update(null, userProjectLambdaUpdateWrapper);
    }

    /**
     * 获取人员下拉框选择数据
     *
     * @return site.morn.rest.RestMessage
     * @author Jereay
     * @date 2024/5/16 10:20
     */
    @Override
    public RestMessage queryProjectUserSelect() {
        // 获取登录用户
        LinkappUser linkappUser = linkappUserContextProducer.getCurrent();
        List<UserProject> list = this.list(Wrappers.<UserProject>lambdaQuery()
                .eq(UserProject::getTenantId, linkappUser.getTenantId())
                .eq(UserProject::getStatus, 1)
                .orderByDesc(UserProject::getCreateTime)
        );
        if(CollectionUtil.isNotEmpty(list)){
            List<UserProjectSelectVO> userProjectSelectVOS = BeanUtil.copyToList(list, UserProjectSelectVO.class);
            return RestBuilders.successBuilder().data(userProjectSelectVOS).build();
        }
        return RestBuilders.successBuilder().data(new ArrayList<>()).build();
    }

    private ExcelResultDetailDTO toCheckAndSave(Integer type, String tenantId, UnzipFileVo vo) {
        ExcelResultDetailDTO result = new ExcelResultDetailDTO();
        result.setName(vo.getPath());
        List<String> msgs = new ArrayList<>();
        //验证大小
        long size = vo.getSize();
        if (vo.getType() == 0) {
            msgs.add("文件夹不可以导入");
        }
        if (size < 8 * 1024 || size > 200 * 1024) {
            msgs.add("照片大小不在8K-200K");
        }
        if (!vo.getPath().endsWith(".jpg")) {
            msgs.add("照片格式不符");
        }
        if (msgs.size() > 0) {
            result.setType(1);
            result.setTypeName("失败");
            result.setDetail(StringUtils.join(msgs, ","));
        } else {
            //查询人员
            String card = vo.getName();
            List<UserProject> userProjects = userProjectMapper.selectByCard(card);
            List<UserProject> users = userProjects.stream()
                    .filter(u -> Integer.valueOf(1).equals(u.getStatus())
                            && tenantId.equals(u.getTenantId())).collect(Collectors.toList());
            if (users.size() < 1) {
                result.setDetail("用户不存在或不在此项目岗位上");
                result.setType(1);
                result.setTypeName("失败");
                return result;
            }
            UserProject userProject = users.get(0);
            //是否覆盖
            if (StringUtils.isNotBlank(userProject.getPhoto())) {
                result.setType(2);
                if (!Integer.valueOf(1).equals(type)) {
                    result.setDetail("重复");
                    result.setTypeName("重复");
                    return result;
                } else {
                    result.setTypeName("覆盖");
                    result.setDetail("覆盖");
                }
            }
            //上传服务器
            try {
                String s = ossService.uploadImg(vo.getInputStream(), userProject.getUserName(), "jpg");
                UpdateWrapper<EmpUserBase> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("photo_", s).eq("card_", card);
                empUserBaseMapper.update(null, updateWrapper);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private Map<String, Object> getUserPhoto(String card, String tenantId) {
        Map<String, Object> map = new HashMap<>();
        //查询已绑定编号的闸机
        String result = null;
        boolean flag = false;
        try {
            QueryWrapper<Gate> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("tenant_id_", tenantId)
                    .isNotNull("code_");
            List<Gate> gates = gateMapper.selectList(queryWrapper);
            Set<String> codeSet = gates.stream().map(g -> g.getCode()).collect(Collectors.toSet());
            if (null != codeSet && codeSet.size() > 0) {
                //查询在不在设备库里
                QueryWrapper<Device> deviceQueryWrapper = new QueryWrapper<>();
                deviceQueryWrapper.in("code", codeSet).eq("online_state", 1);
                List<Device> devices = deviceMapper.selectList(deviceQueryWrapper);
                Set<String> codes = devices.stream().map(g -> g.getCode()).collect(Collectors.toSet());
                if (null != codes && codes.size() > 0) {
                    Iterator<String> iterator = codes.iterator();
                    while (iterator.hasNext()) {
                        String code = iterator.next();
                        Map<String, Object> downParameter = new HashMap<>();
                        //设备编号
                        downParameter.put("device_id", code);
                        Map<String, Object> parameter = new HashMap<>();
                        parameter.put("id", card);
                        downParameter.put("parameter", parameter);
                        downParameter.put("service_id", "queryPersonById");
                        ApiDownResultDTO send = deviceServiceService.send(downParameter);
                        if ("0".equals(send.getCode())) {
                            flag = true;
                            String message = send.getMsg();
                            if (StringUtils.isNotBlank(message)) {
                                //处理msg
                                result = "data:image/jpg;base64," + message.substring(message.indexOf("image_data=") + 11, message.indexOf(")]"));
                                break;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        map.put("photo", result);
        map.put("flag", flag);
        return map;
    }

    /**
     * 同步到东西湖智慧监管平台
     */

    private void syncToSystem(EmpUserBaseDTO empUserBaseDTO, int isDeleted) {
        new Thread(() -> {
            logger.info("实名制信息开始同步到东西湖智慧监管平台");
            //封装请求参数
            RealNameSystemDTO dto = new RealNameSystemDTO();

            Date joinTime1 = empUserBaseDTO.getUserProject().getJoinTime();

            Group group = new Group();
            if (!StringUtils.isBlank(empUserBaseDTO.getUserProject().getGroupId())) {
                group = groupMapper.selectById(empUserBaseDTO.getUserProject().getGroupId());
                if (group != null) {
                    empUserBaseDTO.getUserProject().setGroupName(group.getName());
                }
            }
            if (empUserBaseDTO.getId() == null) {
                //新增的数据要获取到项目名称
                String companyProjectId = empUserBaseDTO.getUserProject().getCompanyProjectId();
                LaborCompanyProject laborCompanyProject = null;
                if (StringUtils.isBlank(companyProjectId)) {
                    if (group != null) {
                        laborCompanyProject = laborCompanyProjectMapper.selectById(group.getCompanyProjectId());
                    }
                } else {
                    laborCompanyProject = laborCompanyProjectMapper.selectById(companyProjectId);
                }

                if (laborCompanyProject != null) {
                    dto.setCompany(laborCompanyProject.getCompanyName());
                }
//                QueryWrapper<LaborCompanyProject> qw = new QueryWrapper<>();
//                qw.eq("id", companyProjectId);
//                List<LaborCompanyProject> laborCompanyProjects = laborCompanyProjectMapper.selectList(qw);
//                if (laborCompanyProjects != null && laborCompanyProjects.size() > 0) {
//                    dto.setCompany(laborCompanyProjects.get(0).getCompanyName());
//                }
                joinTime1 = new Date();

            } else {
                dto.setCompany(empUserBaseDTO.getUserProject().getCompanyName());
            }
            //证书没有读写权限。不传了
//        List<UserCertificate> userCertificates = empUserBaseDTO.getUserCertificates();
//        List<String> listPhoto = new ArrayList<>();
//        if (userCertificates != null && userCertificates.size() > 0) {
//            userCertificates.forEach(item -> {
//                listPhoto.add(Base64Util.getImgStrToBase64(item.getUrl()));
//            });
//        }
//        dto.setCertificatePhotoList(listPhoto);
            //将图片地址转为base64字符串
            String img64 = Base64Util.getImgStrToBase64(empUserBaseDTO.getPhoto());
            dto.setHeadImage(img64);//img64
            dto.setIdNum(empUserBaseDTO.getCard());
            dto.setIsDelet(isDeleted);
            dto.setName(empUserBaseDTO.getName());
            dto.setPhone(empUserBaseDTO.getTelephone());
            dto.setProjectName("cookie测试项目");//测试环境填固定
            dto.setSectionName("cookie测试标段");//测试环境填固定
            dto.setSex(empUserBaseDTO.getUserProject().getGender());
            dto.setTeam(empUserBaseDTO.getUserProject().getGroupName());
            dto.setWorkStatus(getStatus(empUserBaseDTO.getUserProject().getStatus()));
            dto.setWorkType(empUserBaseDTO.getUserProject().getWorkType());

            String joinTime = com.easylinkin.linkappapi.common.utils.DateUtil.getYYYYMMDDDate(joinTime1);
            String leaveTime = com.easylinkin.linkappapi.common.utils.DateUtil.getYYYYMMDDDate(empUserBaseDTO.getUserProject().getLeaveTime());
            dto.setEntryTime(joinTime);
            dto.setDepartureTime(leaveTime);

            String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
            new Thread(new DataSyncUtil(dockingMapper, infoMapper, "[" + JSONObject.toJSONString(dto) + "]", "/assessHardware" +
                    "/rjStaffInfo/saveOrUpdateStaffInfo", tenantId)).start();
        }).start();
    }

    private Integer getStatus(int status) {

        if (status == 0) {
            return 1;
        }
        return 0;
    }
}
